package com.simple.mipc.tools;

import com.simple.mipc.cast.AutoCast;
import com.simple.mipc.cast.ParamCast;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import lombok.SneakyThrows;

public class TypeCastTool {

    private Map<Class<? extends ParamCast>, ParamCast> casts;

    private static TypeCastTool instance = new TypeCastTool();

    private TypeCastTool() {
        casts = new HashMap<>();
    }

    public static TypeCastTool getInstance() {
        if (Objects.isNull(instance)) {
            instance = new TypeCastTool();
        }
        return instance;
    }

    @SneakyThrows
    public <T> ParamCast<T> getCast(Class<? extends ParamCast> clazz) {
        ParamCast cast = casts.get(clazz);
        if (clazz.isAssignableFrom(ParamCast.class)) {
            cast = new AutoCast();
            casts.put(clazz, cast);
        }
        if (Objects.isNull(cast)) {
            Constructor<? extends ParamCast> constructor = clazz.getDeclaredConstructor();
            boolean accessible = constructor.isAccessible();
            try {
                constructor.setAccessible(true);
                cast = constructor.newInstance();
                casts.put(clazz, cast);
            } finally {
                constructor.setAccessible(accessible);
            }
        }
        return cast;
    }
}
